package com.snail.starter.feign.decode;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snail.starter.commons.error.CommonErrorCode;
import com.snail.starter.commons.exception.BizException;
import com.snail.starter.commons.result.ApiResult;
import feign.Request;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author: snail framework
 * @Date: 2023/2/22 下午4:42
 * @Version: 1.0.0
 */
@Slf4j
@Component
public class BasicFeignResponseErrorDecode implements ErrorDecoder {

    @Resource
    ObjectMapper objectMapper;

    @Override
    public Exception decode(String s, Response response) {
        String body = null;
        Request request = response.request();
        HttpStatus httpStatus = HttpStatus.valueOf(response.status());
        String header = null;
        try {
            body = Util.toString(response.body().asReader(StandardCharsets.UTF_8));
        } catch (IOException e) {
            log.error("", e);
            try {
                header = objectMapper.writeValueAsString(request.headers());
            } catch (Throwable ex) {
                log.warn("", e);
            }
            log.error("BasicFeignResponseErrorDecode decode error url:{}, method:{},headers:{},response status:{}", request.url(), response.request().httpMethod(),
                    header, httpStatus.value());
            throw BizException.of(CommonErrorCode.SYSTEM_ERROR.getCode(), body);
        }
        if (null == body || "".equals(body)) {
            log.error("BasicFeignResponseErrorDecode response is empty url:{}, method:{},headers:{},response status:{},body:{}", request.url(), response.request().httpMethod(),
                    header, httpStatus.value(), body);
            throw BizException.of(CommonErrorCode.BIZ_ERROR.getCode(), body);
        }
        ApiResult<?> apiResult;
        try {
            apiResult = objectMapper.readValue(body, ApiResult.class);
        } catch (JsonProcessingException e) {
            log.error("BasicFeignResponseErrorDecode format url:{}, method:{},headers:{},response status:{},body:{}", request.url(), response.request().httpMethod(),
                    header, httpStatus.value(), body);
            throw BizException.of(CommonErrorCode.SYSTEM_ERROR.getCode(), body);
        }
        throw BizException.of(apiResult.getCode(), apiResult.getMsg());
    }
}
